/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.motorola.studio.android.model.java;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.osgi.util.NLS;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.TextEdit;
import com.motorola.studio.android.codeutils.i18n.CodeUtilsNLS;
import com.motorola.studio.android.common.exception.AndroidException;
import com.motorola.studio.android.common.log.StudioLogger;
/**
* Class used to create an Android Content Provider building block class
*/
public class ContentProviderClass extends JavaClass
{
private static final String CP_SUPERCLASS = "android.content.ContentProvider";
private static final String[] URI_CLASS = getFQNAsArray("android.net.Uri");
private static final String[] CONTENTVALUES_CLASS =
getFQNAsArray("android.content.ContentValues");
private static final String[] CURSOR_CLASS = getFQNAsArray("android.database.Cursor");
private static final String DELETE_METHOD_NAME = "delete";
private static final String GETTYPE_METHOD_NAME = "getType";
private static final String INSERT_METHOD_NAME = "insert";
private static final String ONCREATE_METHOD_NAME = "onCreate";
private static final String QUERY_METHOD_NAME = "query";
private static final String UPDATE_METHOD_NAME = "update";
private static final String CONTENT_SCHEME = "content://";
private static final String CONTENT_URI_NAME = "CONTENT_URI";
private ASTRewrite rewrite;
private String authority;
/**
* Default constructor
*
* @param className The simple class name
* @param packageName The full-qualified class package name
*/
public ContentProviderClass(String className, String packageName, String authority)
{
super(className, packageName, CP_SUPERCLASS);
Assert.isNotNull(authority);
this.authority = authority;
addBasicCPInfo();
}
/**
* Adds basic information to the content provider class
*/
@SuppressWarnings("unchecked")
private void addBasicCPInfo()
{
ImportDeclaration importDecl;
// Adds import for Uri
importDecl = ast.newImportDeclaration();
importDecl.setName(ast.newName(URI_CLASS));
compUnit.imports().add(importDecl);
// Adds import for ContentValues
importDecl = ast.newImportDeclaration();
importDecl.setName(ast.newName(CONTENTVALUES_CLASS));
compUnit.imports().add(importDecl);
// Adds import for Cursor
importDecl = ast.newImportDeclaration();
importDecl.setName(ast.newName(CURSOR_CLASS));
compUnit.imports().add(importDecl);
// Adds the authorities constants
addAuthority();
// Adds the delete method
addDeleteMethod();
// Adds the getType method
addGetTypeMethod();
// Adds the insert method
addInsertMethod();
// Adds the onCreate method
addOnCreateMethod();
// Adds the query method
addQueryMethod();
// Adds the update method
addUpdateMethod();
// Adds JavaDoc to elements
addComment(classDecl, CodeUtilsNLS.MODEL_ContentProviderClass_ContentProviderDescription);
}
/**
* Adds the default content provider Uri
*/
@SuppressWarnings("unchecked")
private void addAuthority()
{
final String URI_PARSE_METHOD = "parse";
String contentUriValue = CONTENT_SCHEME + authority;
StringLiteral stringLiteral = ast.newStringLiteral();
stringLiteral.setLiteralValue(contentUriValue);
Name uri = ast.newSimpleName(getName(URI_CLASS));
MethodInvocation parse = ast.newMethodInvocation();
parse.setExpression(uri);
parse.setName(ast.newSimpleName(URI_PARSE_METHOD));
parse.arguments().add(stringLiteral);
VariableDeclarationFragment contentUri = ast.newVariableDeclarationFragment();
contentUri.setName(ast.newSimpleName(CONTENT_URI_NAME));
contentUri.setInitializer(parse);
FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(contentUri);
fieldDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
fieldDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.STATIC_KEYWORD));
fieldDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.FINAL_KEYWORD));
fieldDeclaration.setType(uriType());
classDecl.bodyDeclarations().add(fieldDeclaration);
addComment(fieldDeclaration, CodeUtilsNLS.MODEL_ContentProviderClass_ContentUriDescription);
}
/**
* Adds the delete method to the content provider class
*/
@SuppressWarnings("unchecked")
private void addDeleteMethod()
{
final String SELECTION_PARAM = "selection";
final String SELECTION_ARGS_PARAM = "selectionArgs";
MethodDeclaration method = ast.newMethodDeclaration();
method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
method.setReturnType2(ast.newPrimitiveType(PrimitiveType.INT));
method.setName(ast.newSimpleName(DELETE_METHOD_NAME));
addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType());
addMethodParameter(method, SELECTION_PARAM, stringType());
addMethodParameter(method, SELECTION_ARGS_PARAM, stringArrayType());
addEmptyBlock(method);
classDecl.bodyDeclarations().add(method);
addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_DeleteMethodDescription);
addMethodReference(method, CP_SUPERCLASS, DELETE_METHOD_NAME, new Type[]
{
uriType(), stringType(), stringArrayType()
});
}
/**
* Adds the getType method to the content provider class
*/
@SuppressWarnings("unchecked")
private void addGetTypeMethod()
{
MethodDeclaration method = ast.newMethodDeclaration();
method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
method.setReturnType2(stringType());
method.setName(ast.newSimpleName(GETTYPE_METHOD_NAME));
addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType());
addEmptyBlock(method);
classDecl.bodyDeclarations().add(method);
addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_GetTypeMethodDescription);
addMethodReference(method, CP_SUPERCLASS, GETTYPE_METHOD_NAME, new Type[]
{
uriType()
});
}
/**
* Adds the insert method to the content provider class
*/
@SuppressWarnings("unchecked")
private void addInsertMethod()
{
final String VALUES_PARAM = "values";
MethodDeclaration method = ast.newMethodDeclaration();
method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
method.setReturnType2(uriType());
method.setName(ast.newSimpleName(INSERT_METHOD_NAME));
addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType());
addMethodParameter(method, VALUES_PARAM, contentValuesType());
addEmptyBlock(method);
classDecl.bodyDeclarations().add(method);
addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_InsertMethodDescription);
addMethodReference(method, CP_SUPERCLASS, INSERT_METHOD_NAME, new Type[]
{
uriType(), contentValuesType()
});
}
/**
* Adds the onCreate method to the content provider class
*/
@SuppressWarnings("unchecked")
private void addOnCreateMethod()
{
MethodDeclaration method = ast.newMethodDeclaration();
method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
method.setReturnType2(ast.newPrimitiveType(PrimitiveType.BOOLEAN));
method.setName(ast.newSimpleName(ONCREATE_METHOD_NAME));
addEmptyBlock(method);
classDecl.bodyDeclarations().add(method);
addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_OnCreateMethodDescription);
addMethodReference(method, CP_SUPERCLASS, ONCREATE_METHOD_NAME, null);
}
/**
* Adds the query method to the content provider class
*/
@SuppressWarnings("unchecked")
private void addQueryMethod()
{
final String PROJECTION_PARAM = "projection";
final String SELECTION_PARAM = "selection";
final String SELECTION_ARGS_PARAM = "selectionArgs";
final String SORT_ORDER_PARAM = "sortOrder";
MethodDeclaration method = ast.newMethodDeclaration();
method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
method.setReturnType2(cursorType());
method.setName(ast.newSimpleName(QUERY_METHOD_NAME));
addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType());
addMethodParameter(method, PROJECTION_PARAM, stringArrayType());
addMethodParameter(method, SELECTION_PARAM, stringType());
addMethodParameter(method, SELECTION_ARGS_PARAM, stringArrayType());
addMethodParameter(method, SORT_ORDER_PARAM, stringType());
addEmptyBlock(method);
classDecl.bodyDeclarations().add(method);
addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_QueryMethodDescription);
addMethodReference(method, CP_SUPERCLASS, QUERY_METHOD_NAME, new Type[]
{
uriType(), stringArrayType(), stringType(), stringArrayType(), stringType()
});
}
/**
* Adds the update method to the content provider class
*/
@SuppressWarnings("unchecked")
private void addUpdateMethod()
{
final String VALUES_PARAM = "values";
final String SELECTION_PARAM = "selection";
final String SELECTION_ARGS_PARAM = "selectionArgs";
MethodDeclaration method = ast.newMethodDeclaration();
method.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
method.setReturnType2(ast.newPrimitiveType(PrimitiveType.INT));
method.setName(ast.newSimpleName(UPDATE_METHOD_NAME));
addMethodParameter(method, getName(URI_CLASS).toLowerCase(), uriType());
addMethodParameter(method, VALUES_PARAM, contentValuesType());
addMethodParameter(method, SELECTION_PARAM, stringType());
addMethodParameter(method, SELECTION_ARGS_PARAM, stringArrayType());
addEmptyBlock(method);
classDecl.bodyDeclarations().add(method);
addComment(method, CodeUtilsNLS.MODEL_ContentProviderClass_UpdateMethodDescription);
addMethodReference(method, CP_SUPERCLASS, UPDATE_METHOD_NAME, new Type[]
{
uriType(), contentValuesType(), stringType(), stringArrayType()
});
}
/* (non-Javadoc)
* @see com.motorola.studio.android.model.java.JavaClass#addComments()
*/
@Override
protected void addComments() throws AndroidException
{
ASTNode todoComment;
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setSource(document.get().toCharArray());
compUnit = (CompilationUnit) parser.createAST(null);
ast = compUnit.getAST();
rewrite = ASTRewrite.create(ast);
todoComment =
rewrite.createStringPlaceholder(CodeUtilsNLS.MODEL_Common_ToDoPutYourCodeHere,
ASTNode.EMPTY_STATEMENT);
TypeDeclaration cpClass = (TypeDeclaration) compUnit.types().get(0);
MethodDeclaration method;
Block block;
// Adds the Override annotation and ToDo comment to all abstract methods
for (int i = 0; i < cpClass.bodyDeclarations().size(); i++)
{
BodyDeclaration bodyDecl = (BodyDeclaration) cpClass.bodyDeclarations().get(i);
if (bodyDecl instanceof MethodDeclaration)
{
method = (MethodDeclaration) bodyDecl;
// Adds the Override annotation
rewrite.getListRewrite(method, method.getModifiersProperty()).insertFirst(
OVERRIDE_ANNOTATION, null);
// Adds the ToDo comment
block = method.getBody();
rewrite.getListRewrite(block, Block.STATEMENTS_PROPERTY).insertFirst(todoComment,
null);
}
}
try
{
// Writes the modifications
TextEdit modifications = rewrite.rewriteAST(document, null);
modifications.apply(document);
}
catch (IllegalArgumentException e)
{
String errMsg =
NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);
StudioLogger.error(ContentProviderClass.class, errMsg, e);
throw new AndroidException(errMsg);
}
catch (MalformedTreeException e)
{
String errMsg =
NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);
StudioLogger.error(ContentProviderClass.class, errMsg, e);
throw new AndroidException(errMsg);
}
catch (BadLocationException e)
{
String errMsg =
NLS.bind(CodeUtilsNLS.EXC_JavaClass_ErrorApplyingCommentsToCode, className);
StudioLogger.error(ContentProviderClass.class, errMsg, e);
throw new AndroidException(errMsg);
}
}
/**
* Returns a new Uri type
*
* @return a new Uri type
*/
private Type uriType()
{
return ast.newSimpleType(ast.newSimpleName(getName(URI_CLASS)));
}
/**
* Returns a new ContentValues type
*
* @return a new ContentValues type
*/
private Type contentValuesType()
{
return ast.newSimpleType(ast.newSimpleName(getName(CONTENTVALUES_CLASS)));
}
/**
* Returns a new Cursor type
*
* @return a new Cursor type
*/
private Type cursorType()
{
return ast.newSimpleType(ast.newSimpleName(getName(CURSOR_CLASS)));
}
}